#ifndef CPU_H
#define CPU_H

/**
 * CPU类
 * 主要包括含虚拟机的寄存器等硬件信息
 * 由模板指定机器字长、指令集架构和内存信息
 */
template<
    typename word_t,    // 机器字长
    typename arch_t     // 指令集架构
> 
class CPU
{
private:
    /**
     * 虚拟机寄存器组 
     * LC-3 共有8个通用寄存器 R0~R7
     * 另外有一个程序计数器 PC 和一个标志寄存器 FLAG
     */
    enum {
        R_R0 = 0,
        R_R1,
        R_R2,
        R_R3,
        R_R4,
        R_R5,
        R_R6,
        R_R7,
        R_PC,          // 程序计数器
        R_FLAG,        // 程序状态字
        R_COUNT
    };
    word_t reg[R_COUNT]; 

    /**
     * CPU 需要执行的指令
     * 由取指部件产生并
     */
    arch_t inst; 

    /**
     * CPU运行信息，由译码器产生
     * op     : 操作码
     * rd     : 目标寄存器
     * rs     : 第一操作数寄存器
     * rt     : 第二操作数寄存器
     * cond   : 条件
     * imm    : 立即数
     */
    word_t op, rd, rs, rt, cond, imm; 

    /**
     * CPU 状态
     * 零表示 CPU 停止运行，非零表示 CPU 正在运行
     */
    int status; 

public:

    /**
     * CPU 常规操作
     * 包括 CPU 初始化、更新标记寄存器、符号扩展、中断等
     */ 
    void   init();                           // 启动 CPU
    int    state();                          // 获取CPU状态
    void   update_flags(word_t);             // 更新标记寄存器
    word_t sign_extend(word_t, word_t);      // 符号位扩展
    void   trap(word_t);                     // CPU 中断

    /**
     * 指令的执行过程
     */ 
    void   fetch();                          // 取指
    void   decode();                         // 译码
    void   run();                            // 执行

    /**
     * 总线钩子
     * 提供 CPU 访问其他部备的接口
     */
    word_t (*load)(word_t);                  // 内存读
    void   (*store)(word_t, word_t);         // 内存写
    char   (*inchar)();                      // 从外部设备输入一个字符
    void   (*outc)(char);                    // 向外部设备输出一个字符
    void   (*outs)(const char *);            // 向外部设备输出一个字符串
    void   (*flush)();                       // 刷新外部设备
};


#endif